package pers.cz.transform;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.LoaderClassPath;

import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

/**
 * @program: postgirl-collection-client
 * @description: JdbcTransformer
 * @author: Cheng Zhi
 * @create: 2022-02-16 09:19
 **/
public class JdbcTransformer implements ITransformer {

    // 类集合
    public final String MARIADB_CLASS_NAME = "org.mariadb.jdbc.MariaDbStatement";           // mariaDb
    public final String ORACLE_CLASS_NAME = "oracle.jdbc.driver.OracleStatement";           // oracle
    public final String FRAME_CLASS_NAME = "jef.database.support.DefaultDbOperListener";    // easyframe

    //public final String[] METHOD_NAMES = {"executeQuery","execute","executeUpdate"};
    public final String[] METHOD_NAMES = {"afterInsert","afterUpdate","afterDelete","afterSelect"};

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

        String finalClassName = className.replace("/", ".");
        if (finalClassName.equals(FRAME_CLASS_NAME)) {
            // 动态修改代码
            try {
                ClassPool classPool = new ClassPool(true);
                classPool.insertClassPath(new LoaderClassPath(loader));
                // 获取目标类
                CtClass ctClass = classPool.get(finalClassName);
                // 获取要监听的方法
                for (int i=0; i< METHOD_NAMES.length; i++) {
                    CtMethod[] declaredMethods = ctClass.getDeclaredMethods(METHOD_NAMES[i]);
                    for (int j=0; j<declaredMethods.length; j++) {
                        CtMethod ctMethod = declaredMethods[j];
                        String src =
                                "{" +
                                        "pers.cz.mock.InterfaceSQlMock.begin($1);" +
                                        "}";
                        ctMethod.insertBefore(src);
                    }
                }

                return ctClass.toBytecode();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    @Override
    public void doInert(String... params) {


    }
}
